using System;
using System.Linq;
using System.Reflection;
using System.Collections.Generic;

namespace Duhking
{
    public class GenericMethodFinder : BaseMethodFinder, IFindMethod
    {
        public MethodInfo FindMatchingMethod(MethodInfo method, Type targetType)
        {
            if (method.IsGenericMethod)
                method = method.GetGenericMethodDefinition();
            return targetType.GetMethods().FirstOrDefault(m => m.IsGenericMethodDefinition
                                                   && NamesMatch(m, method)
                                                   && ParametersMatch(m,method)
                                                   && ConstraintsMatch(m, method));
        }
        private IEnumerable<Type> GetConstraints(MethodInfo method)
        {
            return method.GetGenericArguments().SelectMany(a => a.GetGenericParameterConstraints());
        }

        private bool ConstraintsMatch(MethodInfo targetMethod, MethodInfo sourceMethod)
        {
            return GetConstraints(sourceMethod).Except(GetConstraints(targetMethod)).Count() == 0;
        }
    }
}
